package com.hmdp.controller;


import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hmdp.dto.Result;
import com.hmdp.dto.ScrollResult;
import com.hmdp.dto.UserDTO;
import com.hmdp.entity.Blog;
import com.hmdp.entity.Follow;
import com.hmdp.entity.User;
import com.hmdp.service.IBlogService;
import com.hmdp.service.IFollowService;
import com.hmdp.service.IUserService;
import com.hmdp.utils.*;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Stream;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author 虎哥
 * @since 2021-12-22
 */
@RestController
@RequestMapping("/blog")
public class BlogController {

    @Resource
    private IBlogService blogService;
    @Resource
    private IUserService userService;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private IFollowService followservice;

    /**
     * 文章有  点赞的redis 和 发布给粉丝的redis。
     *
     * @param blog
     * @return
     */
    @PostMapping
    public Result saveBlog(@RequestBody Blog blog) {
        // 1.获取登录用户
        UserDTO user = UserHolder.getUser();
        blog.setUserId(user.getId());
        // 2.保存探店博文
        blogService.save(blog);
//        点赞的redis。
        stringRedisTemplate.opsForZSet().add(RedisConstant.Blog_liked + blog.getId().toString(), "0", System.currentTimeMillis());
//        3.查询所有的粉丝 根据数据库查出。
        List<Follow> followUserId = followservice.query().eq("follow_user_id", user.getId()).list();
        for (Follow follow : followUserId) {
            //        4.推送给文章id给所有粉丝。
            long userId = follow.getUserId();
            String key = "free:" + userId;
            follow.getFollowUserId();
            stringRedisTemplate.opsForZSet().add(key, blog.getId().toString(), System.currentTimeMillis());
        }
//   5. 返回id
        return Result.ok(blog.getId());
    }

    /**
     * 这是设置是否点赞
     * 根据文章的redis点赞的，保存点赞用户的id   存储进去数据库。
     *
     * @param id
     * @return
     */
    @PutMapping("/like/{id}")
    public Result likeBlog(@PathVariable("id") Long id) {
        // 修改点赞数量
//        update blog set liked =liked +1 where id = ?
        String blogLiked_key = RedisConstant.Blog_liked + id;
        Double score = stringRedisTemplate.opsForZSet().score(blogLiked_key, UserHolder.getUser().getId().toString());

        if (score != null) {
//            如果点赞过了，就取消点赞。
            boolean isSuccess = blogService.update().setSql("liked = liked - 1").eq("id", id).update();
            if (isSuccess) {
                stringRedisTemplate.opsForZSet().remove(blogLiked_key, UserHolder.getUser().getId().toString());
            }
            return Result.ok();
        } else {
//            如果没有点赞过，就可以点赞。
            boolean isSuccess = blogService.update().setSql("liked = liked + 1").eq("id", id).update();
            if (isSuccess) {
                stringRedisTemplate.opsForZSet().add(blogLiked_key, UserHolder.getUser().getId().toString(), System.currentTimeMillis());
            }
            return Result.ok();
        }
    }

    /// 给返回文章添加样式。
    public void isBlogLike(Blog blog) {
        String blogLiked_key = RedisConstant.Blog_liked + blog.getId();
        //1. 获取当前用户信息
        UserDTO userDTO = UserHolder.getUser();
        //当用户未登录时，就不判断了，直接return结束逻辑
        if (userDTO == null) {
            return;
        }
        if (blogLiked_key == null) {
            throw new HmdpException(ResultCodeEnum.LOGIN_AUTH);
        }
        Double score = stringRedisTemplate.opsForZSet().score(blogLiked_key, userDTO.getId().toString());
        blog.setIsLike(score != null);
    }

    @GetMapping("/of/me")
    public Result queryMyBlog(@RequestParam(value = "current", defaultValue = "1") Integer current) {
        // 获取登录用户
        UserDTO user = UserHolder.getUser();
        // 根据用户查询
        Page<Blog> page = blogService.query().eq("user_id", user.getId()).page(new Page<>(current, SystemConstants.MAX_PAGE_SIZE));
        // 获取当前页数据
        List<Blog> records = page.getRecords();
        return Result.ok(records);
    }

    /**
     * 查询出所有的文章，之后给每一篇文章，判断是否点赞过。找出头像和名字。
     * @param current
     * @return
     */
    @GetMapping("/hot")
    public Result queryHotBlog(@RequestParam(value = "current", defaultValue = "1") Integer current) {
        //
        Page<Blog> page = blogService.query().orderByDesc("liked").page(new Page<>(current, SystemConstants.MAX_PAGE_SIZE));
        // 获取当前页数据
        List<Blog> records = page.getRecords();
        // 查询用户 查看文章是否有点击过。
        records.forEach(blog -> {
            Long userId = blog.getUserId();
            User user = userService.getById(userId);
            blog.setName(user.getNickName());
            blog.setIcon(user.getIcon());
            isBlogLike(blog);
        });
        return Result.ok(records);
    }


    @GetMapping("/likes/{id}")
    public Result queryBlogUsers(@PathVariable Integer id) {
        List<UserDTO> userDTOS = blogService.queryBlogLikes(id);
        return Result.ok(userDTOS);
    }

    @GetMapping("/{id}")
    public Result queryById(@PathVariable Integer id) {
        return Result.ok(blogService.queryBlogById(Long.valueOf(id)));
    }

    // BlogController
    @GetMapping("/of/user")
    public Result queryBlogByUserId(@RequestParam(value = "current", defaultValue = "1") Integer current, @RequestParam("id") Long id) {
        // 根据用户查询
        Page<Blog> page = blogService.query().eq("user_id", id).page(new Page<>(current, SystemConstants.MAX_PAGE_SIZE));
        // 获取当前页数据
        List<Blog> records = page.getRecords();
        return Result.ok(records);
    }

    /**
     * @param max    范围  就是lasttime。
     * @param offset 偏移量   ，如果有n个最小范围，那就是n个。
     * @return
     */
    @GetMapping("/of/follow")
    public Result queryBlogOfFollow(@RequestParam("lastId") Long max, @RequestParam(value = "offset", defaultValue = "0") Integer offset) {
        ScrollResult scrollResult = blogService.queryBlogOfFollow(max, offset);
        return Result.ok(scrollResult);
    }
}
